#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>
#include <unistd.h>
#include <fcntl.h>
#include <cJSON.h>
#include <sys/ioctl.h>
#include "Element.h"
#include <time.h>
#include <curl/curl.h>
#include "ArrayList.h"
#include <pthread.h> 


/*共享内存申请标记*/
#define PERM S_IRUSR|S_IWUSR

int play_flag;
/*孙子进程id号*/
pid_t gradchild;

/*子进程id号*/
pid_t pid;

/*共享内存描述标记*/
int shmid;
char *p_addr;
int startplay = 0;
int FM_flag = 0;
int fd_cmd=0;
ArrayList *array;

int get_FMurl(int fm_count, MUSIC *music);
int resume(char *url) ;
pthread_mutex_t mutex;

/*******************************************************  
*功能：        向mplayer接收命令的有名管道写数据  
*参数：        mplayer接收命令的管道描述符：fd_cmd  
            命令字符串1：cmd_str  
*返回值：   无  
********************************************************/  
static int write_cmd_to_mplayer_fifo(int fd_cmd, char *cmd_str)  
{  
    int length = 0;  
    int flag = 0;  
      
    pthread_mutex_lock(&mutex);  
    //printf("cmd_str = [%s]\n", cmd_str);  
  
    length = write(fd_cmd, cmd_str, strlen(cmd_str));  
    if(length != strlen(cmd_str))  
    {  
        perror("write command error!");  
        flag = -1;  
    }  
    pthread_mutex_unlock(&mutex);  
  
    return flag;  
}  

/*******************************************************  
*功能：        发送命令给mplayer  
*参数：        mplayer接收命令的管道描述符：fd_cmd  
            命令字符串1：cmd_str1  
            命令字符串2：cmd_str2  
*返回值：   成功：0，失败：-1  
********************************************************/  
int send_cmd_to_mplayer(int fd_cmd, char *cmd_str1, char *cmd_str2)  
{  
  
    int flag = 0;  
    char cmd_str[300];  
  
    bzero(cmd_str, sizeof(cmd_str));  
      
    /*发送pause命令的情况*/  
    if((strcmp(cmd_str1, "pause\n") == 0))    
    {  
  
        if(startplay == 1)        // 0:当前暂停 1:正常播放  
        {  
  
            startplay = 0;  
        }  
        else if(startplay == 0)  
        {  
            startplay = 1;  
        }  
  
        sprintf(cmd_str, "%s", cmd_str1);  
        flag = write_cmd_to_mplayer_fifo(fd_cmd, cmd_str);  
    }  
    /*命令带一个参数情况下(loadfile,seek)的命令发送*/  
    else if((strcmp(cmd_str1, "loadfile ") == 0)||(strcmp(cmd_str1, "seek ") == 0))  
    {  
        sprintf(cmd_str, "%s%s", cmd_str1, cmd_str2);  
        flag = write_cmd_to_mplayer_fifo(fd_cmd, cmd_str);  
    }  
    /*正常播放情况下的命令发送*/  
    else  
    {  
        if(startplay == 1)  
        {  
            sprintf(cmd_str, "%s", cmd_str1);  
            flag = write_cmd_to_mplayer_fifo(fd_cmd, cmd_str);  
        }  
    }  
    usleep(300000);  
    return flag;  
} 


int sql_find(int id, MUSIC *music) {
  sqlite3 *db = NULL;
  char *errMsg;
  int rc;
  char sql_string[64];
  char **azResult; //二维数组存放结果
  sprintf(sql_string, "select * from KTV where  (id=%d);", id);
  int row = 0, column = 0;
  rc = sqlite3_open("/MyDB/Music.db", &db);
  if ( rc )    {
    sqlite3_close(db);
    return row;
  }
  sqlite3_get_table(db , sql_string , &azResult , &row , &column , &errMsg);
  if (row <= 0) {
    return 0;
  }
  sprintf(music->id , "%s", azResult[column]);
  sprintf(music->name , "%s", azResult[column + 1]);
  sprintf(music->player , "%s", azResult[column + 2]);
  sprintf(music->path , "%s", azResult[column + 3]);
  return row;
}

void play(MUSIC *music)
{
  pid_t fd;
  char *c_addr;
  char *p;
  int len;

  while (play_flag)
  {
    /*创建子进程，即孙子进程*/
    fd = fork();
    if (fd == -1)
    {
      perror("fork");
      exit(1);
    }
    else if (fd == 0) //孙子进程
    {
      printf("music name = %s play_flager = %s\n path = %s\n", music->name, music->player, music->path);

      execl("/usr/bin/mplayer", "mplayer","-ac", "mad", "-slave", "-quiet", "-input", "file=/tmp/cmd_fifo", "-fs",music->path,"-zoom", "-x 800", "-y 480", NULL); 
      //播放当前列表MP3音乐
      //execl("/usr/bin/mplayer", "mplayer","-ac", "mad", "-slave", "-quiet", "-input", "file=/tmp/cmd_fifo", music->path, NULL); 
      sleep(20);
      printf("\n\n\n");
    }
    else //子进程
    {
      /*内存映射*/
      c_addr = shmat(shmid, 0, 0);

      /*把孙子进程的id和当前播放歌曲的节点指针传入共享内存*/
      memcpy(c_addr, &fd, sizeof(pid_t));

      if (fd == wait(NULL))
      {
       /* if (FM_flag)
        {
          int id = (int)music->id[0] - '0';
          get_FMurl(id, music);
        } else {*/
          play_flag = 0;
          int id = (int)music->id[0] - '0';
          printf("music->id %d\n",id);
          system("echo \"quit\" > /tmp/cmd_fifo");
        //}
      }
    }
  }
}

void stop_Music(pid_t g_pid)
{
  if (startplay) {
    printf("+-------------------- STOPPED --------------------+\n");
    kill(g_pid, SIGKILL); //对孙子进程发送SIGKILL信号
    kill(pid, SIGKILL);  //对子进程发送SIGKILL信号
    startplay = 0;
  }
}

void pause_Music(pid_t pid)
{
  printf("+-------------------- PAUSED--------------------+\n");
  kill(pid, SIGSTOP); //对孙子进程发送SIGSTOP信号
  play_flag = 0;
}

void conti_play(pid_t pid)
{
  printf("+-------------------- CONTINUE --------------------+\n");
  kill(pid, SIGCONT); //对孙子进程发送SIGCONT信号
  play_flag = 1;
}


void sound_volume(int value){
  if(fd_cmd){
    char *vol_str;
    sprintf(vol_str,"volume %d i",value);
    send_cmd_to_mplayer(fd_cmd,vol_str,NULL);
  }
}

void sound_right()
{
  system("echo \"balance 0.2\" > /tmp/cmd_fifo");
  printf("+-------------------- RIGHT --------------------+\n");
}

void sound_left()
{
  system("echo \"balance -0.2\" > /tmp/cmd_fifo");
  printf("+-------------------- LEFT --------------------+\n");
}

void playlist_delete(MUSIC *music)
{
  removeElement(array,*music);
}

void playlist_read(){
  open("../tables/dataKTV.json",O_RDWR);
}

void playlist_add(MUSIC *music)
{
  addElement(array,*music);
}

void playlist_top(MUSIC *music)
{
  setElement(array,*music,1);
}

void playlist_next()
{
  MUSIC *music = getElement(array,0);
  removeElement(array,*music);
  if(array){};
}


int play_Music(pid_t *childpid, MUSIC *music) {
  pid_t pid;
  int ret;
  pid = fork();

  if (pid > 0)
  {
    *childpid = pid; //子进程PID初始化
    play_flag = 1;
    sleep(1);
    /*读取共享内存保存的pid,初始化孙子进程的pid*/
    memcpy(&gradchild, p_addr, sizeof(pid_t));
  }
  else if (0 == pid) //子进程
  {
    /*子进程播放MP3函数*/
    play(music);
    printf("+-------------------- PLAY --------------------+\n");
  }
  return 0;
}

#define STOP 0
#define PAUSE 1
#define CONTI 2
#define PLAY 3
#define TOP 4
#define NEXT 5
#define ADD 6
#define DETETE 7
#define READ  8
#define RIGHT 9
#define LEFT 10
#define VOLUME 11
#define NC 12
#define COM_NUM 13

#define READ_ID 254

void command_Music(int com, int fd) {
  int id;
  MUSIC music;
  FM_flag = 0;
  switch (com) {
  case STOP: stop_Music(gradchild); break; //stop
  case PAUSE: pause_Music(gradchild); break; //pause
  case CONTI: conti_play(gradchild); break; //conti
  case PLAY: {       //play
    ioctl(fd, READ_ID, 0);
    read(fd, &id, sizeof(id));
    if (startplay) {
      stop_Music(gradchild);
    }
    if (sql_find(id, &music) > 0) {
      play_flag = 1;
      play_Music(&pid, &music);
      startplay = 1;
    }
  } break;
  case TOP:{
    ioctl(fd, READ_ID, 0);
    read(fd, &id, sizeof(id));
    if (sql_find(id, &music) > 0) {
      playlist_top(&music);
    }
  } break;
  case NEXT: {
    if (startplay) {
      stop_Music(gradchild);
    }
    playlist_next();
  }break;
  case RIGHT:{
    sound_right();
  } break;
  case LEFT:{
    sound_left();
  } break;
  case NC: break;
  }
}

int main(void) {
  int fd;
  int com;
  int old_id = 0;
  fd = open("/dev/KTV", O_RDWR, 664);
  fd_cmd = open("/tmp/cmd_fifo",O_RDWR);
  array=createArrayList(cmp,prt); 
  if (fd < 0) {
    printf("can't open\n");
    return -1;
  }
  /*共享内存：用于存放子进程ID，播放列表位置*/
  if ((shmid = shmget(IPC_PRIVATE, 1, PERM)) == -1)
    exit(1);
  p_addr = shmat(shmid, 0, 0);
  memset(p_addr, '\0', 1024);
  while (1) {
    read(fd, &com, 4);
    //printf("%s\n",com );
    if (com < COM_NUM) {
      command_Music(com, fd);
      com = NC;
      write(fd, &com, 4);
    }
    sleep(1);
  }
  stop_Music(gradchild);
  close(fd);
  return 0;
}


